package cn.tedu.tmall.front.mall.service.impl;


import cn.tedu.tmall.common.pojo.po.MallCacheCategoryPO;
import cn.tedu.tmall.common.pojo.vo.MallCategoryTreeVO;
import cn.tedu.tmall.front.mall.dao.repository.ICategoryCacheRepository;
import cn.tedu.tmall.front.mall.dao.repository.ICategoryRepository;
import cn.tedu.tmall.front.mall.pojo.po.CategoryPO;
import cn.tedu.tmall.front.mall.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 服务层-商城分类接口实现类
 */
@Slf4j
@Service
public class CategoryService implements ICategoryService {
    @Autowired
    private ICategoryRepository categoryRepository;

    @Autowired
    private ICategoryCacheRepository categoryCacheRepository;

    /**
     * 简单本地缓存  https://blog.csdn.net/zzzili/article/details/131326504
     */
    private Map<String,List<MallCategoryTreeVO>> cached = new HashMap<>();

    @Override
    public void initCategory() {
        //使用已有的方法获取全部分类
        List<MallCategoryTreeVO> mallCategoryTreeVOS = treeCategoryFromDB();
        //存入缓存
        categoryCacheRepository.saveCategoryTree(mallCategoryTreeVOS);
    }

    @Override
    public List<MallCategoryTreeVO> treeCategory() {
        return categoryCacheRepository.getCategoryTree();
    }

    /**
     * 获取分类树
     * 业务逻辑：先获取顶级分类，再递归获取子级分类，直到isParent=0
     */
    public List<MallCategoryTreeVO> treeCategoryFromDB() {
        //简单的缓存使用
//        String key = "ALL";
//        List<MallCategoryTreeVO> cachedVO = cached.get(key);
//        if (!CollectionUtils.isEmpty(cachedVO)){
//            return cachedVO;
//        } else {
            //获取全部分类
            List<CategoryPO> allCategoryPOS = categoryRepository.getAll();
            log.debug("Service-获取全部分类-all:{}",allCategoryPOS);
            //获取顶级分类
            List<MallCategoryTreeVO> topCategoryVOS = getTopCategory(allCategoryPOS);
            log.debug("Service-获取顶级分类-top:{}",topCategoryVOS);
            //获取子级分类
            for (MallCategoryTreeVO topCategoryVO : topCategoryVOS) {
                getChildCategory(topCategoryVO,allCategoryPOS);
            }
            return topCategoryVOS;
//        }
    }

    /**
     * 延迟加载策略-获取顶级分类树
     */
    @Override
    public List<MallCategoryTreeVO> treeTopCategory() {
        //尝试从缓存获取顶级分类
        List<MallCacheCategoryPO> cacheTopCategory = categoryCacheRepository.getTopCategory();
        //如果结果不为空，说明有缓存，直接返回结果
        if (!CollectionUtils.isEmpty(cacheTopCategory)){
            log.debug("Service-从缓存获取顶级分类-top:{}",cacheTopCategory);
            return cacheCategoryPOS2VOS(cacheTopCategory);
        } else { //如果结果为空，说明没有缓存，从数据库获取
            log.debug("Service-从缓存获取顶级分类为空");
            List<CategoryPO> dbTopCategoryPOS = categoryRepository.getTopCategory();
            //获取到的结果不为空，则放入缓存
            if (!CollectionUtils.isEmpty(dbTopCategoryPOS)){
                List<MallCacheCategoryPO> mallCacheCategoryPOS = categoryPOS2CachePOS(dbTopCategoryPOS);
                categoryCacheRepository.saveCategory(mallCacheCategoryPOS);
                log.debug("Service-从数据库获取顶级分类-top:{}",dbTopCategoryPOS);
                return categoryPOS2VOS(dbTopCategoryPOS);
            } else {
                log.error("Service-从数据库获取顶级分类为空");
            }
        }
        return Collections.emptyList();

    }

    /**
     * 延迟加载策略-获取子级分类树
     */
    @Override
    public List<MallCategoryTreeVO> treeChildrenCategory(Long parentId) {
        //尝试从缓存获取子级分类
        List<MallCacheCategoryPO> cacheChildrenCategory = categoryCacheRepository.getChildrenCategory(parentId);
        //如果结果不为空，说明有缓存，直接返回结果
        if (!CollectionUtils.isEmpty(cacheChildrenCategory)){
            log.debug("Service-从缓存获取子级分类-top:{}",cacheChildrenCategory);
            return cacheCategoryPOS2VOS(cacheChildrenCategory);
        } else { //如果结果为空，说明没有缓存，从数据库获取
            log.debug("Service-从缓存获取子级分类为空");
            List<CategoryPO> dbChildrenCategoryPOS = categoryRepository.getChildrenCategory(parentId);
            //获取到的结果不为空，则放入缓存
            if (!CollectionUtils.isEmpty(dbChildrenCategoryPOS)){
                List<MallCacheCategoryPO> mallCacheCategoryPOS = categoryPOS2CachePOS(dbChildrenCategoryPOS);
                categoryCacheRepository.saveChildrenCategory(parentId,mallCacheCategoryPOS);
                log.debug("Service-从数据库获取子级分类-top:{}",dbChildrenCategoryPOS);
                return categoryPOS2VOS(dbChildrenCategoryPOS);
            } else {
                log.error("Service-从数据库获取子级分类为空");
            }
        }
        return Collections.emptyList();
    }

    /**
     * 从所有分类中获取顶级分类
     * @param categoryPOS 所有分类
     * @return List<CategoryPO> topCategory
     */
    private List<MallCategoryTreeVO> getTopCategory(List<CategoryPO> categoryPOS){
        List<MallCategoryTreeVO> topCategory = new ArrayList<>();
        for (CategoryPO po : categoryPOS) {
            if (po.getParentId() == 0)
                topCategory.add(categoryPO2VO(po));
        }
        return topCategory;
    }

    /**
     * 追加子级分类
     */
    private MallCategoryTreeVO getChildCategory(MallCategoryTreeVO vo, List<CategoryPO> all){
        List<MallCategoryTreeVO> childrenCategory = new ArrayList<>();
        for (CategoryPO po : all) {
            if (vo.getId().equals(po.getParentId())){
                MallCategoryTreeVO childVO = categoryPO2VO(po);
                childrenCategory.add(getChildCategory(childVO,all));
            } else {
                //直到isParent=0, 退出循环
            }
        }
        vo.setChildren(childrenCategory);
        return vo;
    }

    /**
     * categoryPO转换为VO
     */
    private MallCategoryTreeVO categoryPO2VO(CategoryPO po){
        MallCategoryTreeVO vo = new MallCategoryTreeVO();
        BeanUtils.copyProperties(po,vo);
        return vo;
    }

    /**
     * categoryPO集合转换为VO集合
     */
    private List<MallCategoryTreeVO> categoryPOS2VOS(List<CategoryPO> categoryPOS){
        List<MallCategoryTreeVO> list = new ArrayList<>();
        for (CategoryPO categoryPO : categoryPOS) {
            list.add(categoryPO2VO(categoryPO));
        }
        return list;
    }

    /**
     * categoryPO转换为cacheCategoryPO
     */
    private MallCacheCategoryPO categoryPO2CachePO(CategoryPO po){
        MallCacheCategoryPO cachePO = new MallCacheCategoryPO();
        BeanUtils.copyProperties(po,cachePO);
        return cachePO;
    }

    /**
     * categoryPO集合转换为cacheCategoryPO集合
     */
    private List<MallCacheCategoryPO> categoryPOS2CachePOS(List<CategoryPO> categoryPOS){
        List<MallCacheCategoryPO> list = new ArrayList<>();
        for (CategoryPO categoryPO : categoryPOS) {
            list.add(categoryPO2CachePO(categoryPO));
        }
        return list;
    }

    /**
     * cacheCategoryPO转换为MallCategoryTreeVO
     */
    private MallCategoryTreeVO cacheCategoryPO2VO(MallCacheCategoryPO cachePO){
        MallCategoryTreeVO categoryTreeVO = new MallCategoryTreeVO();
        BeanUtils.copyProperties(cachePO,categoryTreeVO);
        return categoryTreeVO;
    }

    /**
     * cacheCategoryPO集合转换为MallCategoryTreeVO集合
     */
    private List<MallCategoryTreeVO> cacheCategoryPOS2VOS(List<MallCacheCategoryPO> cachePOS){
        List<MallCategoryTreeVO> list = new ArrayList<>();
        for (MallCacheCategoryPO cachePO : cachePOS) {
            list.add(cacheCategoryPO2VO(cachePO));
        }
        return list;
    }

}
